package cn.crism.service;

import cn.crism.dao.SysDeptMapper;
import cn.crism.exception.PermissionException;
import cn.crism.model.SysDept;
import cn.crism.param.DeptParam;
import cn.crism.utils.BeanValidator;
import cn.crism.utils.LevelUtil;
import com.google.common.base.Preconditions;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * @CreateDate: 2018/12/13 3:35 PM
 * @Description:
 * @Author: Crism
 */
@Service
public class SysDeptService {

    @Resource
    private SysDeptMapper sysDeptMapper;

    public void saveDept(DeptParam param) {
        BeanValidator.check(param);
        if (checkExist(param.getId(), param.getParentId(), param.getName())) {
            throw new PermissionException("同一层级下存在相同名称的部门");
        }
        SysDept dept = SysDept.builder()
                .parentId(param.getParentId())
                .name(param.getName())
                .remark(param.getRemark())
                .seq(param.getSeq()).build();
        dept.setLevel(LevelUtil.calculateLevel(getLevel(param.getParentId()), param.getParentId()));
        dept.setOperator("crism"); // TODO:
        dept.setOperateIp("127.0.0.1"); // TODO:
        dept.setOperateTime(new Date());
        sysDeptMapper.insertSelective(dept);
    }

    public void updateDept(DeptParam param) {
        BeanValidator.check(param);
        if (checkExist(param.getId(), param.getParentId(), param.getName())) {
            throw new PermissionException("同一层级下存在相同名称的部门");
        }
        /* 判断要更新的上级部门是否存在 */
        if (!LevelUtil.ROOT.equals(param.getParentId()+"")){
            SysDept father = sysDeptMapper.selectByPrimaryKey(param.getParentId());
            Preconditions.checkNotNull(father, "上级  部门不存在");
        }
        SysDept before = sysDeptMapper.selectByPrimaryKey(param.getId());
        /* 为空抛出异常 */
        Preconditions.checkNotNull(before, "待更新的部门不存在");
        /* 创建一个更新后的部门信息 */
        SysDept after = SysDept.builder()
                .id(param.getId())
                .parentId(param.getParentId())
                .name(param.getName())
                .remark(param.getRemark())
                .seq(param.getSeq()).build();
        after.setLevel(LevelUtil.calculateLevel(getLevel(param.getParentId()), param.getParentId()));
        after.setOperator("crism"); // TODO:
        after.setOperateIp("127.0.0.1"); // TODO:
        after.setOperateTime(new Date());
        System.out.println("---------------============----------");
        System.out.println(after);
        /* 更新子级元素 */
        updateWithChild(before, after);
    }

    @Transactional
    void updateWithChild(SysDept before, SysDept after) {
        String newLevelPrefix = after.getLevel();
        String oldLevelPrefix = before.getLevel();
        /* 新旧层级后缀不相同则更新子级元素 */
        if (!after.getLevel().equals(before.getLevel())) {
            /* 取出所有子级元素 */
            List<SysDept> deptList = sysDeptMapper.getChildDeptListByLevel(before.getLevel() +"."+ before.getId() + "%");
            System.out.println("-------------------" + before.getLevel() +"."+ before.getId() + "%");
            System.out.println(deptList);
            if (CollectionUtils.isNotEmpty(deptList)) {
                for (SysDept dept : deptList) {
                    String level = dept.getLevel();
                    if (level.indexOf(oldLevelPrefix) == 0) {
                        level = newLevelPrefix + level.substring(oldLevelPrefix.length());
                        dept.setLevel(level);
                    }
                }
                /* 批量更新子级元素level */
                sysDeptMapper.batchUpdateChildLevel(deptList);
            }
        }
        sysDeptMapper.updateByPrimaryKey(after);
    }

    public boolean checkExist(Integer deptId, Integer parentId, String deptName) {
        return sysDeptMapper.countByNameAndParentId(deptId, parentId, deptName) > 0;
    }

    private String getLevel(Integer deptId) {
        SysDept dept = sysDeptMapper.selectByPrimaryKey(deptId);
        if (dept == null) {
            return null;
        }
        return dept.getLevel();
    }

}
